package org.ns.summer.classpath.classreader;


import org.ns.summer.classpath.classreader.basicinfo.MemberInfo;
import org.ns.summer.classpath.classreader.basicinfo.attribute.AttributeInfo;
import org.ns.summer.classpath.classreader.basictype.U2;
import org.ns.summer.classpath.classreader.basictype.U4;
import org.ns.summer.classpath.classreader.constantinfo.ConstantClass;
import org.ns.summer.classpath.classreader.constantinfo.ConstantUtf8;
import org.ns.summer.classpath.classreader.entity.ClassInfo;
import org.ns.summer.classpath.classreader.entity.ClassInfoUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

/**
 * 读取class文件
 */
public class ClassReader {
	public static ClassFile read(String classPath) {
		File file = new File(classPath);
		try {
			return read(new FileInputStream(file));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static ClassFile read(InputStream in) {

		try (InputStream inputStream = in;) {
			ClassFile classFile = new ClassFile();
			classFile.magic = U4.read(inputStream);
			classFile.minorVersion = U2.read(inputStream);
			classFile.majorVersion = U2.read(inputStream);

			// 解析常量池
			int constant_pool_count = U2.read(inputStream);
			ConstantPool constantPool = new ConstantPool(constant_pool_count);
			constantPool.read(inputStream);
			classFile.constantPool = constantPool;
			// 获取常量池信息
			// constantPool.printConstanPoolInfo(constantPool);

			// 获取类信息
			classFile.accessFlag = U2.read(inputStream);
			int classIndex = U2.read(inputStream);
			ConstantClass clazz = (ConstantClass) constantPool.cpInfo[classIndex]; // 获取类名，并将其转化为ContantClass类
			ConstantUtf8 classNamec = (ConstantUtf8) constantPool.cpInfo[clazz.nameIndex];
			classFile.className = classNamec.value;

			// 获取父类信息
			int superIndex = U2.read(inputStream);
			ConstantClass superClazz = (ConstantClass) constantPool.cpInfo[superIndex];
			ConstantUtf8 superclassName = (ConstantUtf8) constantPool.cpInfo[superClazz.nameIndex];
			classFile.superClass = superclassName.value;

			// 获取接口信息
			classFile.interfaceCount = U2.read(inputStream);
			classFile.interfaces = new String[classFile.interfaceCount];
			for (int i = 0; i < classFile.interfaceCount; i++) {
				int interfaceIndex = U2.read(inputStream);
				ConstantClass interfaceClazz = (ConstantClass) constantPool.cpInfo[interfaceIndex];
				ConstantUtf8 interfaceName = (ConstantUtf8) constantPool.cpInfo[interfaceClazz.nameIndex];
				classFile.interfaces[i] = interfaceName.value;

			}

			// 获取字段信息
			classFile.fieldCount = U2.read(inputStream);
			classFile.fields = new MemberInfo[classFile.fieldCount];
			for (int i = 0; i < classFile.fieldCount; i++) {
				MemberInfo fieldInfo = new MemberInfo(constantPool);
				fieldInfo.read(inputStream);
			}

			// 获取方法信息
			classFile.methodCount = U2.read(inputStream);
			classFile.methods = new MemberInfo[classFile.methodCount];
			for (int i = 0; i < classFile.methodCount; i++) {
				MemberInfo methodInfo = new MemberInfo(constantPool);
				methodInfo.read(inputStream);
			}

			// 储存类的一些属性
			classFile.attributeCount = U2.read(inputStream);
			classFile.attributes = new AttributeInfo[classFile.attributeCount];
			for (int i = 0; i < classFile.attributeCount; i++) {
				classFile.attributes[i] = new AttributeInfo(constantPool);
				classFile.attributes[i].read2(inputStream);
			}
			return classFile;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static ClassInfo getClassInfoByClassFile(ClassFile classFile) {
		if (classFile == null) {
			return null;
		}

		String className = ClassInfoUtils.getThisClassName(classFile); // 当前类名
		String superName = ClassInfoUtils.getSuperClassName(classFile); // 父类名称
		String[] interfaces = ClassInfoUtils.getInterfaces(classFile); // 接口名称集合
		String[] annotations = ClassInfoUtils.getRuntimeAnnotations(classFile); // 类上拥有的注解
		int accessFlag = classFile.accessFlag;
		return new ClassInfo(className, superName, interfaces, annotations, accessFlag);
	}

}
